Vulnerability reports

Memory corruption vulnerabilities in Suricata and FreeRDP

As a cybersecurity company, before we release our products, we perform penetration tests on them to make sure they are secure. Recently, new versions of KasperskyOS-based products were released, namely Kaspersky Thin Client (KTC) and Kaspersky IoT Secure Gateway (KISG). As part of the pre-release penetration testing, we analyzed two open-source components used in these products, namely Suricata and FreeRDP projects, and discovered several vulnerabilities, which we reported to the developers of the corresponding libraries, as well as sharing the fuzzing tests we used to test FreeRDP.

The community confirmed the reported issues and registered the following CVEs:

Later, using our fuzzing tests, the community found about 10 more vulnerabilities in FreeRDP. All issues were fixed in both open-source projects and in our products prior to the new version releases.

Open-source components in KasperskyOS-based products

KasperskyOS is a microkernel operating system designed to build Cyber Immune products. The attack surface is minimized by the built-in security mechanisms, the small size of the microkernel and domain (component) isolation. The latter allows secure implementation of open-source components: even if a particular component contains vulnerabilities, the isolation prevents most of the damage that could be caused by their exploitation.

The KasperskyOS-based products in question are complex, support various protocols and applications and include open-source components that implement some of their functions. As its name suggests, FreeRDP is an open-source implementation of Remote Desktop Protocol. It is used in Kaspersky Thin Client, where it is responsible for remote connection capabilities.

Suricata is a network monitoring, intrusion detection and prevention system developed by the Open Information Security Foundation and the Suricata community. It is widely used and implemented by most public and private organizations. When it comes to KasperskyOS-based products, Suricata is used in KISG, where it is responsible for detecting network attacks. It receives a copy of network traffic, analyzes it according to a set of rules and issues alerts if an attack is detected.

Although component isolation in KasperskyOS ensures the security of our products even if an open-source component contains vulnerabilities, when assessing the security of our products we follow the defense-in-depth approach. The OS design minimizes the attack surface, but it can’t stop cybercriminals and high-profile actors from trying to find a way to penetrate the system. That’s why we test (and, if necessary, fix) all components of our products, including the open-source projects we use.

Penetration testing begins by describing the entire attack surface, which includes all components and all known attack vectors against them.

CVE-2024-32664: out-of-bounds write in Suricata

During our penetration testing activities we found three issues in Suricata. Two of them were considered bad practice, and one was registered as CVE-2024-32664. The vulnerability affects all Suricata versions from 6.0.0 to 6.0.18 and from 7.0.0 to 7.0.4, and is fixed in versions 6.0.19 and 7.0.5. It was initially assessed as being a medium severity issue (CVSS 5.3). However, in the tickets on the Open Information Security Foundation website, the severity was changed to high for versions 7.0.x and to critical for 6.0.x.

The vulnerability resides in Suricata’s base64 decoding function, DecodeBase64, and belongs to the out-of-bounds write type. In a situation where the buffer is full, it is possible to use specially crafted input to trick the function into thinking that there is some space left and writing three more bytes to the buffer. In base64, if the size of the unencoded data is not a multiple of three, a padding is added to the encoded output. It typically equals one or two. The decoding function accepts encoded data as input, which means that the padding is controlled by the attacker. If they provide an encoded string where the padding equals three or four, a memory corruption occurs, leading to a limited buffer overflow, which may result in remote code execution.

Vulnerable code in Suricata:line 45 – if 'padding' is equal to B64_BLOCK(4) or ASCII_BLOCK(3), 'numDecoded_blk' will be set to 0;
line 46 – we will pass this check, as 'dest_size' is equal to '*decoded_bytes'; 
line 53 – 3 bytes will be written past the end of buffer 'dptr';
line 72 – similar issue.

Vulnerable code in Suricata:
line 45 – if ‘padding’ is equal to B64_BLOCK(4) or ASCII_BLOCK(3), ‘numDecoded_blk’ will be set to 0;
line 46 – we will pass this check, as ‘dest_size’ is equal to ‘*decoded_bytes’;
line 53 – 3 bytes will be written past the end of buffer ‘dptr’;
line 72 – similar issue.

The issue was patched in Suricata versions 6.0.19 and 7.0.5. For those, who are unable to install these updates, the following recommendations to mitigate the threat were provided by the community:

  • Do not load untrusted datasets
  • Do not use rules with a ‘base64_decode’ keyword with a ‘bytes’ option with a value of 1, 2 or 5

For the software versions 7.0.x you can also set ‘app-layer.protocols.smtp.mime.body-md5’ to false.

FreeRDP vulnerabilities

The vulnerabilities in FreeRDP were found using a simple FreeRDP fuzzer. They affect all FreeRDP 3.x.x versions prior to 3.5.0 and all FreeRDP 2.x.x versions prior to 2.11.6, where they were fixed.

CVE-2024-32041

This vulnerability resides in the zgfx_decompress_segment function of the ZGFX decoder and is an out-of-bounds read vulnerability. The absence of a necessary check may lead to a situation where a certain number of bytes of data are accessed that shouldn’t be.

This vulnerability may be exploited by a malicious server to gain access to a portion of the client memory. It may be used to bypass address space layout randomization (ASLR) to get the address space layout for a particular process and perform an attack against that process.

Vulnerable code in the 'zgfx_decompress_segment' function:line 48 – the variable 'count' is checked to make sure it is not greater than the size of allocated space in the output buffer;
lines 54-55 – the variable 'count' is not checked against the size of the decoded array. Hence the out-of-bounds read.

Vulnerable code in the ‘zgfx_decompress_segment’ function:
line 48 – the variable ‘count’ is checked to make sure it is not greater than the size of allocated space in the output buffer;
lines 54-55 – the variable ‘count’ is not checked against the size of the decoded array. Hence the out-of-bounds read.

As a workaround for users who cannot install the fixed version of FreeRDP, the community recommends deactivating the “/gfx” connection method, which is on by default, and set “/bpp” or “/rfx” instead.

CVE-2024-32039

This is an integer overflow and out-of-bounds write vulnerability in the clear_decompress_residual_data function in the Clear codec component. The ‘runLengthFactor’ variable is read from the stream, which can be controlled by the attacker. The code performs a sanity check to make sure it is not bigger than the size of the array to be written to. This sanity check contains an error that allows the attacker to bypass it via unsigned integer overflow and write outside the allocated buffer. Exploitation of this vulnerability could lead to remote code execution on the client.

Vulnerable code in the 'clear_decompress_residual_data' function:line 23 – the variable 'runLengthFactor' is an unsigned integer (uint32);
line 42 – the variable 'runLengthFactor' is read from the stream;
line 47 – due to an unsigned integer overflow, if the 'runLengthFactor' value is large enough, the 'pixelIndex+runLengthFactor' value approaches zero, and the check is passed;
lines 56-60 – the 'for' cycle uses the original 'runLengthFactor' value and is written outside 'dstBuffer'.

Vulnerable code in the ‘clear_decompress_residual_data’ function:
line 23 – the variable ‘runLengthFactor’ is an unsigned integer (uint32);
line 42 – the variable ‘runLengthFactor’ is read from the stream;
line 47 – due to an unsigned integer overflow, if the ‘runLengthFactor’ value is large enough, the ‘pixelIndex+runLengthFactor’ value approaches zero, and the check is passed;
lines 56-60 – the ‘for’ cycle uses the original ‘runLengthFactor’ value and is written outside ‘dstBuffer’.

As a workaround for the unpatched versions, it is recommended to use “/bpp:32” or “/rfx” instead of the “/gfx” codec that is enabled by default.

CVE-2024-32040

This integer underflow vulnerability affects FreeRDP connections that use the NSC codec responsible for bitmap compression. It resides in the nsc_rle_decode function of this component. The absence of a necessary check may lead to a situation when the size of unprocessed input data is less than 0. As it is an unsigned integer variable, it will become a large positive value in this case. This may lead to an out-of-bounds read of a large amount of data.

Vulnerable code in the nsc_rle_decode function:lines 45-48 – the variable 'len' is read from the attacker-controlled stream;
line 51 – suppose 'len' is a large integer and it is less than 'outSize', thus we can pass this check;
line 57 – there is no check to ensure that 'left' is greater than 'len', which may result in an unsigned integer underflow, and the big value of the 'left' variable;
line 6 – the big value of the 'left' variable passes the check, and the next iteration starts reading outside the memory bounds.

Vulnerable code in the nsc_rle_decode function:
lines 45-48 – the variable ‘len’ is read from the attacker-controlled stream;
line 51 – suppose ‘len’ is a large integer and it is less than ‘outSize’, thus we can pass this check;
line 57 – there is no check to ensure that ‘left’ is greater than ‘len’, which may result in an unsigned integer underflow, and the big value of the ‘left’ variable;
line 6 – the big value of the ‘left’ variable passes the check, and the next iteration starts reading outside the memory bounds.

As a workaround in a situation where installing the patched version is impossible, it is recommended not to use the codec in question.

CVE-2024-32458

This is an out-of-bounds read vulnerability in the planar_skip_plane_rle function in the Planar codec component. No checks are implemented for the planes array elements in the function code. As a result, the SrcSize variable may exceed the amount of available data, which may result in an out-of-bounds read. An attacker may attempt to bypass ASLR using this vulnerability.

Vulnerable code in the planar_skip_plane_rle function:line 13 – no check is performed to ensure the size is no less than the offset to plane. If it is small enough, an unsigned integer underflow occurs;
line 45 – as a result, SrcSize can exceed the amount of available data;
line 52 – out-of-bounds read on this line.

Vulnerable code in the planar_skip_plane_rle function:
line 13 – no check is performed to ensure the size is no less than the offset to plane. If it is small enough, an unsigned integer underflow occurs;
line 45 – as a result, SrcSize can exceed the amount of available data;
line 52 – out-of-bounds read on this line.

You can find the fix for the vulnerability here. As a workaround for unpatched systems, it is recommended to use “/gfx” or “/rfx” connection methods. Note that the “/gfx” method is enabled by default and it is recommended to disable it to mitigate other vulnerabilities in this list.

CVE-2024-32459

This is an out-of-bounds read vulnerability in ncrush_decompress function of the ncrush codec. If the source data size is small, up to four extra bytes could be read, which could be used to bypass ASLR.

Vulnerable code in the 'ncrush_decompress' function:Line 18 – Out-of-bounds read if SrcSize is less than 4.

Vulnerable code in the ‘ncrush_decompress’ function:
Line 18 – Out-of-bounds read if SrcSize is less than 4.

There are no workarounds for the unpatched versions of the FreeRDP client.

CVE-2024-32460

This is an out-of-bounds read vulnerability in ExtractRunLengthLiteFgBg function in the Interleaved codec component. It affects FreeRDP clients that use the legacy “GDI” drawing path for transmitting graphics from the remote desktop. This function accepts the pointer to the first element after the allocated buffer and incorrectly handles the ‘buffer_within_range’ helper, causing it to read one byte outside the buffer.

Vulnerable code in the ExtractRunLengthLiteFgBg function:line 11 – 'pbEnd' points to the first byte after the end of buffer;
line 26 – the 'ExtractRunLength' function is called with 'pbEnd' as the third parameter;
line 51 – the 'ExtractRunLengthLiteFgBg' function is called with 'pbEnd' as a second parameter;
line 77 – the 'ExtractRunLengthLiteFgBg' function checks that there is one byte before the end of the buffer;
line 82 – the code reads one byte outside of the allocated buffer.

Vulnerable code in the ExtractRunLengthLiteFgBg function:
line 11 – ‘pbEnd’ points to the first byte after the end of buffer;
line 26 – the ‘ExtractRunLength’ function is called with ‘pbEnd’ as the third parameter;
line 51 – the ‘ExtractRunLengthLiteFgBg’ function is called with ‘pbEnd’ as a second parameter;
line 77 – the ‘ExtractRunLengthLiteFgBg’ function checks that there is one byte before the end of the buffer;
line 82 – the code reads one byte outside of the allocated buffer.

You can find the fix for the vulnerability here. The workaround for unpatched systems could be to use more recent settings such as “/gfx” or “/rfx” if the server supports them. Note that some of the other vulnerabilities in this list affect FreeRDP clients that use “/gfx” as the drawing path.

We shared our fuzzing tests with the FreeRDP community, along with information about the vulnerabilities that were found. They ran them against various codecs used in the software and found 10 more vulnerabilities in the following components:

  • Clear codec
  • Color codec
  • Interleaved codec
  • NSC codec
  • ZGFX codec

Most of these vulnerabilities are out-of-bounds reads that can be used to bypass the ASLR security measure. All of them were fixed in versions 3.5.1 and 2.11.7.

Disclosure timeline

  • 28.03.2024 – We shared information about the vulnerabilities with the Suricata community.
  • 15.04.2024 – We reported the discovered vulnerabilities to the FreeRDP community.
  • 16.04.2024 – FreeRDP fixes issued.
  • 20.04.2024 – Fixes issued for the vulnerabilities discovered by the community using our fuzzer.
  • 23.04.2024 – Patched Suricata versions issued.

Conclusion

The concept of secure by design applies not only to system architecture, but also to the development process itself. Moreover, by testing and trying all the system components prior to release, we were able to help the community fix a range of issues in two widely used open-source projects. We would like to thank the Suricata and FreeRDP maintainers for their quick response to our reports and prompt release of the patches.

If you use this software, we encourage you to update to the latest versions as soon as possible. At the time of publication, the most up-to-date versions are:

  • 6.0.20 and 7.0.6 for Suricata;
  • 2.11.7 and 3.7.0 for FreeRDP.

Memory corruption vulnerabilities in Suricata and FreeRDP

Your email address will not be published. Required fields are marked *

 

Reports

APT trends report Q3 2024

The report features the most significant developments relating to APT groups in Q3 2024, including hacktivist activity, new APT tools and campaigns.

Subscribe to our weekly e-mails

The hottest research right in your inbox